﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration;

namespace PolicyInjectionExtension
{
    #region PolicyInjectionExtensionHelper class
    public abstract class PolicyInjectionHelper : IDisposable
    {
        protected readonly IUnityContainer container;
        protected static readonly TransparentProxyInterceptor injector = new TransparentProxyInterceptor();

        #region constructors
        public PolicyInjectionHelper()
        {
            container = new UnityContainer();
            container.AddNewExtension<Interception>();
        }
        
        #endregion

        #region Do actions: DoWrap, DoCreate
        private object DoWrap(object instance, Type typeToReturn)
        {
            container.Configure<Interception>().SetDefaultInterceptorFor(typeToReturn, injector);

            return container.BuildUp(typeToReturn, instance);
        }

        private object DoCreate(Type typeToCreate, Type typeToReturn, object[] arguments)
        {
            object target = Activator.CreateInstance(typeToCreate, arguments);
            return DoWrap(target, typeToReturn);
        }
        #endregion

        #region Wraps
        public object Wrap(object instance, Type typeToReturn)
        {
            return DoWrap(instance, typeToReturn);
        }

        public TInterface Wrap<TInterface>(object instance)
        {
            return (TInterface)Wrap(instance, typeof(TInterface));
        }
        #endregion

        #region Creates
        public object Create(Type typeToCreate, Type typeToReturn, params object[] args)
        {
            return DoCreate(typeToCreate, typeToReturn, args);
        }

        public object Create(Type typeToCreate, params object[] args)
        {
            return Create(typeToCreate, typeToCreate, args);
        }

        public TInterface Create<TObject, TInterface>(params object[] args)
        {
            return (TInterface)Create(typeof(TObject), typeof(TInterface), args);
        }

        public TObject Create<TObject>(params object[] args)
        {
            return (TObject)Create(typeof(TObject), typeof(TObject), args);
        }
        #endregion

        #region Dispose
        void IDisposable.Dispose()
        {
            if (this.container != null)
            {
                this.container.Dispose();
            }
        }
        #endregion
    }
    #endregion
}
